<template>
  <div class="cesium-viewer-wapper">
    <div id="cesium-viewer" />
    <viewerSettingSidebar top="18em" :viewerSource="viewerSource" />
    <div class="tool-box-top-left">
      <div class="select-box-wrapper"><select-box :options="flyOptions" /></div>
      <div class="select-box-wrapper"><a-checkbox v-model:checked="clippingPlanesEnabled">Clipping Planes Enabled</a-checkbox></div>
      <div class="select-box-wrapper"><a-checkbox v-model:checked="edgeStylingEnabled">Edge Styling Enabled</a-checkbox></div>
    </div>
    <GlobeRotater showTime :viewerSource="viewerSource" />
    <MousePosition show :viewerSource="viewerSource" />
  </div>
</template>

<script>
import * as Cesium from '@cesiumjs';
import { defineComponent, ref, watch, toRaw } from 'vue';
import { SelectBox, SliderBar } from '@components/widgets';
import { G3V } from '@g3x';
import { MousePosition, viewerSettingSidebar, GlobeRotater } from '@g3x/g3v/ui';
import {viewerMixin} from '@mixins';
import merge from '@g3x/utils/merge';

const $g3vOptions = {
  // defaultViewRectangle: G3V.defaultViews.global.china.rectangle,
  viewers: [
    {
      dom: 'cesium-viewer',
      name: 'viewer1',
      title: 'viewer#01',
      viewer: {
        imagery: { type: 'arcgisImagery', options: { brightness: 1, show: true } },
        imageryProvider: null,
        terrain: { type: 'default', options: { requestVertexNormals: true, requestWaterMask: true } },
        terrainProvider: null,
        shadows: false,
        scene3DOnly: true,
        // sceneMode: Cesium.SceneMode.SCENE2D,
        animation: false
      },
      layers: [
        { type: 'osmImagery', options: { brightness: 1, show: false } },
        { type: 'arcgisStreetMap', options: { brightness: 1, show: false } },
        { type: 'bingMapsImagery', options: { brightness: 1, show: false } },
        { type: 'tdtIboMap', options: { brightness: 1, show: false } },
        { type: 'tdtImgAnno', options: { brightness: 1, show: false } },
        {
          type: 'graticule',
          options: {
            brightness: 1,
            show: true
          }
        }
      ],
      globe: {
        depthTestAgainstTerrain: true,
        enableLighting: true //启用以太阳为光源的地球
      },
      bottomContainer: false,
      navigation: {
        // defaultResetView: G3V.defaultViews.global.china.rectangle ,
        defaultResetView: null //flyHome
      },
      shortcutAction: false,
      hideLayers: false
    }
  ]
};

export default defineComponent({
  name: 'fly', // 飞行动画
  mixins: [viewerMixin],
  components: { SelectBox, SliderBar, viewerSettingSidebar, GlobeRotater, MousePosition },
  props: {},
  setup() {
    return {};
  },
  data() {
    return {
      flyOptions: [],
      edgeStylingEnabled: true,
      clippingPlanesEnabled: true
    };
  },
  computed: {},
  watch: {
    edgeStylingEnabled(val) {
      this.viewer.scene.globe.clippingPlanes.edgeWidth = val ? 1.0 : 0.0;
    },
    clippingPlanesEnabled(val) {
      this.viewer.scene.globe.clippingPlanes.enabled = val;
    }
  },
  methods: {
    g3vOptionsGet(original) {
      // const g3vOptions = merge($g3vOptions, true);
      return $g3vOptions;
    },
    onViewerInited() {
      console.log('fly onViewerInited');
    },
    initEffects() {
      const vm = this;
      const { viewer } = vm;
      const globe = viewer.scene.globe;

      this.flyOptions = [
        {
          text: '请选择'
        },
        {
          text: 'Curry Village',
          onselect: function() {
            reset();
            loadCesiumMan();
          }
        },
        {
          text: 'St. Helens',
          onselect: function() {
            reset();
            loadStHelens();
          }
        },
        {
          text: 'Grand Canyon Isolated',
          onselect: function() {
            reset();
            loadGrandCanyon();
          }
        }
      ];

      var tileset;

      loadCesiumMan();

      function reset() {
        globe.clippingPlanes.removeAll()
        viewer.entities.removeAll();
        viewer.scene.primitives.remove(tileset);
      }

      function loadCesiumMan() {
        var position = Cesium.Cartesian3.fromRadians(-2.0862979473351286, 0.6586620013036164, 1400.0);

        var entity = viewer.entities.add({
          position: position,
          box: {
            dimensions: new Cesium.Cartesian3(1400.0, 1400.0, 2800.0),
            material: Cesium.Color.WHITE.withAlpha(0.5),
            outline: true,
            outlineColor: Cesium.Color.WHITE.withAlpha(0.25)
          }
        });

        globe.depthTestAgainstTerrain = true;
        globe.clippingPlanes = new Cesium.ClippingPlaneCollection({
          modelMatrix: entity.computeModelMatrix(Cesium.JulianDate.now()),
          planes: [
            new Cesium.ClippingPlane(new Cesium.Cartesian3(1.0, 0.0, 0.0), -700.0),
            new Cesium.ClippingPlane(new Cesium.Cartesian3(-1.0, 0.0, 0.0), -700.0),
            new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 1.0, 0.0), -700.0),
            new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, -1.0, 0.0), -700.0)
          ],
          edgeWidth: vm.edgeStylingEnabled ? 1.0 : 0.0,
          edgeColor: Cesium.Color.WHITE,
          enabled: vm.clippingPlanesEnabled
        });
        globe.backFaceCulling = true;
        globe.showSkirts = false;

        viewer.trackedEntity = entity;
      }

      function loadStHelens() {
        // Create clipping planes for polygon around area to be clipped.
        var points = [
          new Cesium.Cartesian3(-2358434.3501556474, -3743554.5012105294, 4581080.771684084),
          new Cesium.Cartesian3(-2357886.4482675144, -3744467.562778789, 4581020.9199767085),
          new Cesium.Cartesian3(-2357299.84353055, -3744954.0879047974, 4581080.992360969),
          new Cesium.Cartesian3(-2356412.05169956, -3745385.3013702347, 4580893.4737207815),
          new Cesium.Cartesian3(-2355472.889436636, -3745256.5725702164, 4581252.3128526565),
          new Cesium.Cartesian3(-2354385.7458722834, -3744319.3823686405, 4582372.770031389),
          new Cesium.Cartesian3(-2353758.788158616, -3743051.0128084184, 4583356.453176038),
          new Cesium.Cartesian3(-2353663.8128999653, -3741847.9126874236, 4584079.428665509),
          new Cesium.Cartesian3(-2354213.667592133, -3740784.50946316, 4584502.428203525),
          new Cesium.Cartesian3(-2355596.239450013, -3739901.0226732804, 4584515.9652557485),
          new Cesium.Cartesian3(-2356942.4170108805, -3740342.454698685, 4583686.690694482),
          new Cesium.Cartesian3(-2357529.554838029, -3740766.995076834, 4583145.055348843),
          new Cesium.Cartesian3(-2358106.017822064, -3741439.438418052, 4582452.293605261),
          new Cesium.Cartesian3(-2358539.5426236596, -3742680.720902901, 4581692.0260975715)
        ];

        var pointsLength = points.length;

        // Create center points for each clipping plane
        var clippingPlanes = [];
        var [x, y, z] = [0, 0, 0];
        for (var i = 0; i < pointsLength; ++i) {
          const point = points[i];
          (x += point.x / pointsLength), (y += point.y / pointsLength), (z += point.z / pointsLength);
          var nextIndex = (i + 1) % pointsLength;
          var midpoint = Cesium.Cartesian3.add(point, points[nextIndex], new Cesium.Cartesian3());
          midpoint = Cesium.Cartesian3.multiplyByScalar(midpoint, 0.5, midpoint);

          var up = Cesium.Cartesian3.normalize(midpoint, new Cesium.Cartesian3());
          var right = Cesium.Cartesian3.subtract(points[nextIndex], midpoint, new Cesium.Cartesian3());
          right = Cesium.Cartesian3.normalize(right, right);

          var normal = Cesium.Cartesian3.cross(right, up, new Cesium.Cartesian3());
          normal = Cesium.Cartesian3.normalize(normal, normal);

          // Compute distance by pretending the plane is at the origin
          var originCenteredPlane = new Cesium.Plane(normal, 0.0);
          var distance = Cesium.Plane.getPointDistance(originCenteredPlane, midpoint);

          clippingPlanes.push(new Cesium.ClippingPlane(normal, distance));
        }

        var position = new Cesium.Cartesian3(x, y, z);
        var distance = 3000.0;
        var boundingSphere = new Cesium.BoundingSphere(position, distance);
        viewer.camera.flyToBoundingSphere(boundingSphere, {
          complete() {
            globe.clippingPlanes = new Cesium.ClippingPlaneCollection({
              planes: clippingPlanes,
              // unionClippingRegions: true,
              edgeWidth: vm.edgeStylingEnabled ? 1.0 : 0.0,
              edgeColor: Cesium.Color.WHITE,
              enabled: vm.clippingPlanesEnabled
            });

            globe.backFaceCulling = false;
            globe.showSkirts = false;
          }
        });
      }

      function loadGrandCanyon() {
        // Pick a position at the Grand Canyon
        var position = Cesium.Cartographic.toCartesian(new Cesium.Cartographic.fromDegrees(-113.2665534, 36.0939345, 100));
        var distance = 3000.0;
        var boundingSphere = new Cesium.BoundingSphere(position, distance);

        viewer.camera.flyToBoundingSphere(boundingSphere, {
          complete() {
            globe.clippingPlanes = new Cesium.ClippingPlaneCollection({
              modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(position),
              planes: [
                new Cesium.ClippingPlane(new Cesium.Cartesian3(1.0, 0.0, 0.0), distance),
                new Cesium.ClippingPlane(new Cesium.Cartesian3(-1.0, 0.0, 0.0), distance),
                new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 1.0, 0.0), distance),
                new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, -1.0, 0.0), distance)
              ],
              unionClippingRegions: true,
              edgeWidth: vm.edgeStylingEnabled ? 1.0 : 0.0,
              edgeColor: Cesium.Color.WHITE,
              enabled: vm.clippingPlanesEnabled
            });
            globe.backFaceCulling = false;
            globe.showSkirts = false;

            // viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0.5, -0.5, boundingSphere.radius * 5.0));
            // viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
          }
        });
      }
    }
  }
});
</script>

<style lang="less">
.cesium-viewer-wapper {
  .tool-box-left-top {
    display: flex;
    button {
      min-width: 5em;
      background-color: rgba(0, 0, 0, 0.75);
      border-color: rgba(0, 0, 0, 0);
      cursor: pointer;
      transition: all 500ms;
      &:hover {
        opacity: 0.75;
      }
      &.active {
        background-color: rgba(0, 20, 200, 0.75);
      }
    }
  }
}
</style>
